﻿#region using

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Linq.Expressions;
using Pentia.Linq.Mapping;

#endregion

namespace Pentia.Linq
{
  public class SitecoreContext<T> : IQueryable<T>, IQueryContext
  {
    private readonly Axis _axisType;
    private readonly string _itemName = null;
    private readonly Item _rootItem;
    private readonly string _templateID;

    public SitecoreContext(Item rootItem, Axis axisType) : this(rootItem, axisType, null)
    {
    }

    public SitecoreContext(Item rootItem, Axis axisType, string itemName)
    {
      if (rootItem == null)
        throw new ArgumentNullException("rootItem");
      _rootItem = rootItem;
      _axisType = axisType;
      _itemName = itemName;
      //Determine the template ID from the type we are requesting
      Type templateType = typeof(T);
      object[] attributes = templateType.GetCustomAttributes(typeof (SitecoreTemplateAttribute), true);
      if (attributes.Length > 0)
      {
        SitecoreTemplateAttribute attribute = (SitecoreTemplateAttribute)attributes[0];
        _templateID = attribute.ID;
      }
    }

    public string TemplateID
    {
      get { return _templateID; }
    }

    public TextWriter Log { get; set; }

    #region IQueryable<T> Members

    public IEnumerator<T> GetEnumerator()
    {
      SitecoreQuery<T> query = new SitecoreQuery<T>(this, Expression) {Log = Log};
      return query.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
      return GetEnumerator();
    }

    public Expression Expression
    {
      get { return Expression.Constant(this); }
    }

    public Type ElementType
    {
      get { return typeof (ISitecoreItem); }
    }

    public IQueryProvider Provider
    {
      get { return new SitecoreQueryProvider(this) {Log = Log}; }
    }

    #endregion

    #region IQueryContext Members

    public Item RootItem
    {
      get { return _rootItem; }
    }

    public Axis AxisType
    {
      get { return _axisType; }
    }

    public string ItemName
    {
      get { return _itemName; }
    }

    #endregion
  }
}